package com.gitee.wsl.doc.prosemirror.state.command.block.list

import com.gitee.wsl.doc.prosemirror.model.attr.Attrs
import com.gitee.wsl.doc.prosemirror.model.content.NodeRange
import com.gitee.wsl.doc.prosemirror.model.content.ext.findWrapping
import com.gitee.wsl.doc.prosemirror.model.fragment.Fragment
import com.gitee.wsl.doc.prosemirror.model.fragment.Slice
import com.gitee.wsl.doc.prosemirror.model.node.NodeBase
import com.gitee.wsl.doc.prosemirror.model.node.NodeType
import com.gitee.wsl.doc.prosemirror.model.node.ext.canSplit
import com.gitee.wsl.doc.prosemirror.state.Command
import com.gitee.wsl.doc.prosemirror.state.CommandDispatch
import com.gitee.wsl.doc.prosemirror.state.EditorState
import com.gitee.wsl.doc.prosemirror.state.Transaction
import com.gitee.wsl.doc.prosemirror.transform.ext.split
import com.gitee.wsl.doc.prosemirror.transform.ext.step
import com.gitee.wsl.doc.prosemirror.transform.step.ReplaceAroundStep

class WrapInList(val listType: NodeType,
                 val attrs:Attrs? = null
):Command {
    override fun exec(
        state: EditorState,
        dispatch: CommandDispatch?,
    ): Boolean {
        val selection = state.selection
        val from = selection._from
        val to = selection._to

        var range = from.blockRange(to)
        var doJoin = false
        var outerRange = range

        // 如果没有有效的范围，返回false
        if (range == null) {
            return false
        }

        // 检查是否在现有列表项的顶部
        if (range.depth >= 2) {
            val parentNode = from.node(range.depth - 1)
            if (parentNode.type.compatibleContent(listType) && range.startIndex == 0) {

                // 如果已经在列表顶部，不执行任何操作
                if (from.index(range.depth - 1) == 0) {
                    return false
                }

                val insertPos = state.doc.resolve(range.start - 2)
                outerRange = NodeRange(insertPos, insertPos, range.depth)

                if (range.endIndex < range.parent.childCount) {
                    val toEnd = to.end(range.depth)
                    val resolvedToEnd = state.doc.resolve(toEnd)
                    range = NodeRange(from, resolvedToEnd, range.depth)
                }
                doJoin = true
            }
        }

        // 查找合适的包装
        val wrap = outerRange.findWrapping( listType, attrs, range)

        if (wrap == null) {
            return false
        }

        // 如果提供了dispatch函数，执行实际的包装操作
        if (dispatch != null) {
            val transaction = doWrapInList(state.tr, range, wrap, doJoin, listType)
            transaction.scrollIntoView()
            dispatch(transaction)
        }

        return true
    }

}

/**
 * 执行列表包装操作
 */
private fun doWrapInList(
    tr: Transaction,
    range: NodeRange,
    wrappers: List<NodeBase>,
    joinBefore: Boolean,
    listType: NodeType
): Transaction {
    // 构建包装内容
    var content = Fragment.empty
    for (i in wrappers.indices.reversed()) {
        val wrapper = wrappers[i]
        val node = wrapper.type.create(wrapper.attrs, content)
        content = Fragment.from(node)
    }

    // 执行替换步骤
    val startPos = range.start - (if (joinBefore) 2 else 0)
    val slice = Slice(content, 0, 0)
    tr.step(ReplaceAroundStep(startPos, range.end, range.start, range.end, slice, wrappers.size, true))

    // 查找列表类型在包装器中的位置
    var found = 0
    for (i in wrappers.indices) {
        if (wrappers[i].type == listType) {
            found = i + 1
        }
    }
    val splitDepth = wrappers.size - found

    // 在适当位置分割节点
    var splitPos = range.start + wrappers.size - (if (joinBefore) 2 else 0)
    val parent = range.parent

    for (i in range.startIndex until range.endIndex) {
        if (i > range.startIndex && tr.doc.canSplit(splitPos, splitDepth)) {
            tr.split(splitPos, splitDepth)
            splitPos += 2 * splitDepth
        }
        splitPos += parent.child(i).nodeSize
    }

    return tr
}
